﻿using System.Drawing;
using System.Runtime.InteropServices;
using Win32Proxy.Api;
using Win32Proxy.Enums;
using Win32Proxy.Structs;

namespace Win32Proxy.Helper
{
    public class MonitorHelper
    {
        public static DisplayDevice[] GetDisplayDevices()
        {
            var devices = new System.Collections.Generic.List<DisplayDevice>();
            uint deviceIndex = 0;
            DISPLAY_DEVICE displayDevice = new();
            displayDevice.cb = Marshal.SizeOf(displayDevice);

            while (User32.EnumDisplayDevices(null, deviceIndex, ref displayDevice, 0))
            {
                if (displayDevice.StateFlags != DisplayDeviceStateFlags.None)
                    devices.Add(new DisplayDevice(displayDevice.DeviceName, displayDevice.DeviceString, displayDevice.StateFlags.HasFlag(DisplayDeviceStateFlags.PrimaryDevice)));
                deviceIndex++;
                displayDevice.cb = Marshal.SizeOf(displayDevice);
            }

            return [.. devices];
        }

        /// <summary>
        /// 获取窗体所在的显示器句柄,配合GetMonitorInfo获取显示器信息
        /// </summary>
        /// <param name="hWnd"></param>
        /// <param name="dwFlags"></param>
        /// <returns></returns>
        public static IntPtr MonitorFromWindow(nint hWnd, uint dwFlags = 0)
        {
            return User32.MonitorFromWindow(hWnd, dwFlags);
        }

        /// <summary>
        /// 获取显示器信息
        /// </summary>
        /// <param name="hMonitor"></param>
        /// <returns></returns>
        public static MonitorInfo GetMonitorInfo(IntPtr hMonitor)
        {
            var monitorInfo = new MonitorInfo();
            monitorInfo.cbSize = (uint)Marshal.SizeOf(monitorInfo);
            User32.GetMonitorInfo(hMonitor, ref monitorInfo);
            return monitorInfo;
        }

        /// <summary>
        /// 获取屏幕分辨率的物理大小，也就是去掉任务栏等占据屏幕空间后的大小。
        /// </summary>
        public static System.Drawing.Size WorkingArea
        {
            get
            {
                nint hdc = User32.GetDC(nint.Zero);
                System.Drawing.Size size = new();
                size.Width = GDI32.GetDeviceCaps(hdc, (int)DeviceCapsIndex.HORZRES);
                size.Height = GDI32.GetDeviceCaps(hdc, (int)DeviceCapsIndex.VERTRES);
                User32.ReleaseDC(nint.Zero, hdc);
                return size;
            }
        }
        /// <summary>
        /// 获取真实的桌面分辨率大小，包括任务栏等占据空间的部分。
        /// </summary>
        public static System.Drawing.Size DesktopResolution
        {
            get
            {
                nint hdc = User32.GetDC(nint.Zero);
                System.Drawing.Size size = new();
                size.Width = GDI32.GetDeviceCaps(hdc, (int)DeviceCapsIndex.DESKTOPHORZRES);
                size.Height = GDI32.GetDeviceCaps(hdc, (int)DeviceCapsIndex.DESKTOPVERTRES);
                User32.ReleaseDC(nint.Zero, hdc);
                return size;
            }
        }
        /// <summary>
        /// 当前系统DPI_X 大小 一般为96, DpiX / 96 = 显示器的缩放比例
        /// </summary>
        public static float DpiX
        {
            get
            {
                IntPtr hdc = User32.GetDC(IntPtr.Zero);
                int DpiX = GDI32.GetDeviceCaps(hdc.ToInt32(), (int)DeviceCapsIndex.LOGPIXELSX);
                User32.ReleaseDC(IntPtr.Zero, hdc);
                return DpiX;
            }
        }

        /// <summary>
        /// 当前系统DPI_Y 大小 一般为96
        /// </summary>
        public static float DpiY
        {
            get
            {
                IntPtr hdc = User32.GetDC(IntPtr.Zero);
                int DpiY = GDI32.GetDeviceCaps(hdc.ToInt32(), (int)DeviceCapsIndex.LOGPIXELSY);
                User32.ReleaseDC(IntPtr.Zero, hdc);
                return DpiY;
            }
        }

        /// <summary>
        /// 获取系统显示宽度缩放百分比
        /// </summary>
        public static float ScaleX
        {
            get
            {
                IntPtr hdc = User32.GetDC(IntPtr.Zero);
                int t = GDI32.GetDeviceCaps(hdc.ToInt32(), (int)DeviceCapsIndex.DESKTOPHORZRES);
                int d = GDI32.GetDeviceCaps(hdc.ToInt32(), (int)DeviceCapsIndex.HORZRES);
                float ScaleX = (float)t / (float)d;
                User32.ReleaseDC(IntPtr.Zero, hdc);
                return ScaleX;
            }
        }

        /// <summary>
        /// 获取系统显示高度缩放百分比
        /// </summary>
        public static float ScaleY
        {
            get
            {
                IntPtr hdc = User32.GetDC(IntPtr.Zero);
                int t = GDI32.GetDeviceCaps(hdc.ToInt32(), (int)DeviceCapsIndex.DESKTOPHORZRES);
                int d = GDI32.GetDeviceCaps(hdc.ToInt32(), (int)DeviceCapsIndex.VERTRES);
                float ScaleY = (float)t / (float)d;
                User32.ReleaseDC(IntPtr.Zero, hdc);
                return ScaleY;
            }
        }

        /// <summary>
        /// 获取屏幕分辨率
        /// </summary>
        /// <param name="lpszDeviceName">显示器名称，例如：screen.DeviceName</param>
        /// <returns></returns>
        public static System.Drawing.Rectangle GetScreenResolution(string lpszDeviceName)
        {
            DEVMODE dm = new()
            {
                dmSize = (short)Marshal.SizeOf(typeof(DEVMODE))
            };
            User32.EnumDisplaySettings(lpszDeviceName, DisplaySettings.ENUM_CURRENT_SETTINGS, ref dm);

            return new(dm.dmPositionX, dm.dmPositionY, dm.dmPelsWidth, dm.dmPelsHeight);
        }
    }
}
